package Client;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import Server.Log;

public class TCPSpellingClient{
	
	private static final int FIVE_SEC = 5000;

	private Socket client_socket;
	
	private DataOutputStream to_server;
	
	private BufferedReader from_server;
	
	private String[] query_words;
	
	/**
	 * @param args Command line arguments.
	 */
	public static void main(String[] args) throws IOException{
		new TCPSpellingClient(args).run();
	}
	
	/**
	 * Constructor for a TCPSpellingClient
	 * @param args Command line arguments from main.
	 */
	public TCPSpellingClient(String [] args){

		try {
			client_socket = new Socket(args[0], Integer.parseInt(args[1]));
			Log.out("Socket opened on port " + client_socket.getLocalPort());
			Log.out("Initialized network.");
			client_socket.setSoTimeout(FIVE_SEC);
			to_server = new DataOutputStream(client_socket.getOutputStream());

			from_server = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
		} catch (SocketException e) {
			Log.err("Unable to create socket (host may not be listening on port)");
			System.exit(1);
		} catch (UnknownHostException e) {
			Log.err("Specified host " + args[0] + " does not exist.");
			System.exit(1);
		} catch (IOException e) {
			Log.err("Error creating streams.");
			System.exit(1);
		}
		
		query_words = new String[args.length-2];

		for(int i=2; i<args.length; i++) {
			query_words[i-2] = args[i];
		}
	
	}
	
	/**
	 * 
	 * @throws IOException
	 */
	private void run() {
		for(int i=1; i<query_words.length+1; i++) {
			Log.out("Querying server (" + query_words[i-1] + ")");
			try {
				to_server.writeBytes(i + " " + query_words[i-1] + '\n');
			} catch (IOException e) {
				Log.err("Unable to send query to server.");
				continue;
			}
			try {
				processReturn(from_server.readLine());
			} catch (IOException e) {
				if(i == query_words.length) {
					Log.err("Timed out on query. No more words to query.");
				} else {
					Log.err("Timed out on query. Proceeding to next word.");
					continue;
				}
			}
		}
		
		try {
			to_server.writeBytes("\n");
			client_socket.close();
		} catch (IOException e) {
			Log.err("Unable to close connection normally.");
		}
	}
	
	private void processReturn(String return_string) {
		
		String[] ret_arr = return_string.split(" ");

		if(ret_arr[0].equals("INVALID")) {
			Log.err("Server responding to malformed packet.");
		} else {

			try {

				if(ret_arr[1].equals("OK")) {
					Log.out(query_words[Integer.parseInt(ret_arr[0])-1] + 
							" was spelled correctly.");
				} else if(ret_arr[1].equals("NO")){
					String suggestions = "";
					for(int i=2; i<ret_arr.length-1; i++) {
						suggestions += ret_arr[i] + ", ";
					}
					suggestions += ret_arr[ret_arr.length-1];

					Log.out(query_words[Integer.parseInt(ret_arr[0])-1] + 
							" not spelled correctly, " + (ret_arr.length-2) + 
							" suggestions: " + suggestions);

				} else if(Integer.parseInt(ret_arr[0]) > query_words.length ||
						Integer.parseInt(ret_arr[0]) < 1){
					Log.err("Received malformed packet: Response index not " +
							"valid.");
				}

			} catch(NumberFormatException e) {
				Log.err("Received malformed packet: first element not " +
						" integer or \"INVALID\"");
			}
		}
		
	}

}
